# -*- coding: utf-8 -*-
"""
    xfree.utils.translations
    ~~~~~~~~~~~~~~~~~~~~~
    文件描述：这个模块包含了 XFree 使用的翻译相关的功能。
    作者：xfree
    邮箱：cy_83k@qq.com
"""
import logging
import os
import subprocess

import babel
from flask import current_app
from flask_babelplus import Domain, get_locale
from flask_babelplus.utils import get_state

logger = logging.getLogger(__name__)


class XFreeDomain(Domain):
    """
    XFree 的翻译域类。
    """
    def __init__(self, app):
        """
        构造函数，初始化翻译域对象。

        参数：
            app：Flask 应用对象。
        """
        self.app = app
        # 调用父类构造函数
        super(XFreeDomain, self).__init__()

        # 插件翻译
        with self.app.app_context():
            self.plugin_translations = self.app.pluggy.hook.xfree_load_translations()

    def get_translations(self):
        """
        获取当前请求应该使用的正确的翻译对象。如果在请求之外使用或者找不到翻译，将不会失败并返回一个空翻译对象。
        """
        state = get_state(silent=True)

        if state is None:
            return babel.support.NullTranslations()

        locale = get_locale()
        cache = self.get_translations_cache()
        translations = cache.get(str(locale))

        # 如果缓存中没有翻译对象，则加载它
        if translations is None:
            dirname = self.get_translations_path(state.app)
            translations = babel.support.Translations.load(
                dirname, locale, domain=self.domain
            )
            # 加载并添加插件翻译
            for plugin in self.plugin_translations:
                logger.debug("正在从 {} 加载插件翻译".format(plugin))
                plugin_translation = babel.support.Translations.load(
                    dirname=plugin, locales=locale, domain="messages"
                )

                if type(plugin_translation) is not babel.support.NullTranslations:
                    translations.add(plugin_translation)

            self.cache[str(locale)] = translations

        return translations


def update_translations(include_plugins=False):
    """
    更新所有翻译。

    参数：
        include_plugins：如果设置为 True，也将更新所有插件的翻译。
    """
    translations_folder = os.path.join(current_app.root_path, "translations")
    source_file = os.path.join(translations_folder, "messages.pot")

    # 提取翻译文本并生成.pot 文件
    subprocess.call(
        [
            "pybabel",
            "extract",
            "-F",
            "babel.cfg",
            "-k",
            "lazy_gettext",
            "-o",
            source_file,
            ".",
        ]
    )
    # 更新翻译文件
    subprocess.call(["pybabel", "update", "-i", source_file, "-d", translations_folder])

    if include_plugins:
        for plugin in current_app.pluggy.list_name():
            update_plugin_translations(plugin)


def add_translations(translation):
    """
    添加新的语言翻译。

    参数：
        translation：翻译的短名称，如“en”或“de_AT”。
    """
    translations_folder = os.path.join(current_app.root_path, "translations")
    source_file = os.path.join(translations_folder, "messages.pot")

    # 提取翻译文本并生成.pot 文件
    subprocess.call(
        [
            "pybabel",
            "extract",
            "-F",
            "babel.cfg",
            "-k",
            "lazy_gettext",
            "-o",
            source_file,
            ".",
        ]
    )
    # 初始化新的语言翻译文件
    subprocess.call(
        [
            "pybabel",
            "init",
            "-i",
            source_file,
            "-d",
            translations_folder,
            "-l",
            translation,
        ]
    )


def compile_translations(include_plugins=False):
    """
    编译所有翻译。

    参数：
        include_plugins：如果设置为 True，也将编译所有插件的翻译。
    """
    translations_folder = os.path.join(current_app.root_path, "translations")
    # 编译翻译文件
    subprocess.call(["pybabel", "compile", "-d", translations_folder])

    if include_plugins:
        for plugin in current_app.pluggy.list_name():
            compile_plugin_translations(plugin)


def add_plugin_translations(plugin, translation):
    """
    为插件添加新的语言翻译。

    参数：
        plugin：插件的标识符。
        translation：翻译的短名称，如“en”或“de_AT”。
    """
    plugin_folder = current_app.pluggy.get_plugin(plugin).__path__[0]
    translations_folder = os.path.join(plugin_folder, "translations")
    source_file = os.path.join(translations_folder, "messages.pot")

    # 提取翻译文本并生成.pot 文件
    subprocess.call(
        [
            "pybabel",
            "extract",
            "-F",
            "babel.cfg",
            "-k",
            "lazy_gettext",
            "-o",
            source_file,
            plugin_folder,
        ]
    )
    # 初始化新的插件语言翻译文件
    subprocess.call(
        [
            "pybabel",
            "init",
            "-i",
            source_file,
            "-d",
            translations_folder,
            "-l",
            translation,
        ]
    )


def update_plugin_translations(plugin):
    """
    更新插件的翻译。如果该插件没有翻译，则返回 False。

    参数：
        plugin：插件的标识符。
    """
    plugin_folder = current_app.pluggy.get_plugin(plugin).__path__[0]
    translations_folder = os.path.join(plugin_folder, "translations")
    source_file = os.path.join(translations_folder, "messages.pot")

    if not os.path.exists(source_file):
        return False

    # 提取翻译文本并生成.pot 文件
    subprocess.call(
        [
            "pybabel",
            "extract",
            "-F",
            "babel.cfg",
            "-k",
            "lazy_gettext",
            "-o",
            source_file,
            plugin_folder,
        ]
    )
    # 更新插件翻译文件
    subprocess.call(["pybabel", "update", "-i", source_file, "-d", translations_folder])


def compile_plugin_translations(plugin):
    """
    编译插件的翻译。如果该插件没有翻译，则返回 False。

    参数：
        plugin：插件的标识符。
    """
    plugin_folder = current_app.pluggy.get_plugin(plugin).__path__[0]
    translations_folder = os.path.join(plugin_folder, "translations")

    if not os.path.exists(translations_folder):
        return False

    # 编译插件翻译文件
    subprocess.call(["pybabel", "compile", "-d", translations_folder])